package com.github.livebase.util.base;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

/**
 * @ClassName Collections
 * @description:
 * @author: biao532
 * @create: 2023-11-23 23:03
 * @Version 1.0
 **/
public class CollectionsUtil {
    @FunctionalInterface
    public interface Filter<T> {
        boolean filter(T t);
    }
    @FunctionalInterface
    public interface SimpleVisitor<T> {
        void visit(T t);
    }

    @FunctionalInterface
    public interface Visitor<T> {
        void visit(int idx, T t);
    }
    @FunctionalInterface
    public interface Converter<T, V> {
        V convert(int i, T t);
    }

    public static boolean isEmpty(Collection collection) {
        return collection == null || collection.isEmpty();
    }

    public static <T, V> List<V> convert(List<T> list, ObjectsUtil.Converter<T, V> converter) {
        if (list == null) {
            return new ArrayList<>(0);
        }
        List<V> l = new ArrayList<>(list.size());
        CollectionsUtil.foreach(list, (c) -> {
            l.add(ObjectsUtil.convert(c, converter));
        });
        return l;
    }
    public static <T, V> List<V> convert(List<T> list, Converter<T, V> converter) {
        List<V> l = new ArrayList<>(list.size());
        CollectionsUtil.foreach(list, (i, c) -> {
            l.add(converter.convert(i, c));
        });
        return l;
    }

    public static<T> int firstIndex(Collection<T> collection, Filter<T> filter) {
        if (collection == null) {
            return -1;
        }
        int i = 0;
        for (T c :collection) {
            if (filter.filter(c)) {
                return i;
            }
            i ++;
        }
        return -1;
    }
    public static<T> T first(Collection<T> collection, Filter<T> filter) {
        if (collection == null) {
            return null;
        }
        for (T c :collection) {
            if (filter.filter(c)) {
                return c;
            }
        }
        return null;
    }
    public static<T> T getOrDefault(List<T> list, int index, T value) {
        if (CollectionsUtil.isEmpty(list) || list.size() <= index || index < 0) {
            return value;
        }
        return list.get(index);
    }
    public static<E> List<E> filter (List<E> collection, Filter<E> filter) {
        if (collection == null) {
            return null;
        }
        List<E> list = new ArrayList<>(collection.size());
        CollectionsUtil.foreach(collection, (c)-> {
            if (filter.filter(c)) {
                list.add(c);
            }
        });
        return list;
    }
    public static<E> void removeAll (Collection<E> collection, Filter<E> filter) {
        if (collection == null) {
            return ;
        }
        Iterator<E> iterator = collection.iterator();
        while (iterator.hasNext()) {
            E c = iterator.next();
            if (filter.filter(c)) {
                iterator.remove();
            }
        }
    }

    public static<E> Collection<E> copy(Collection<E> collection) {
        if (collection == null) {
            return null;
        }
        List<E> list = new ArrayList<>(collection.size());
        for (E c : collection) {
            list.add(c);
        }
        return list;
    }

    public static<E> List<E> asList(E... items) {
        if (items == null) {
            return new ArrayList<>(0);
        }
        List<E> list = new ArrayList<>(items.length);
        for (E c : items) {
            list.add(c);
        }
        return list;
    }

    public static<T> void foreach(Collection<T> collection, SimpleVisitor<T> simpleVisitor) {
        CollectionsUtil.foreach(collection, (c)-> {
            simpleVisitor.visit(c);
            return true;
        });
    }
    public static<T> void foreach(Collection<T> collection, Visitor<T> visitor) {
        if (collection == null) {
            return;
        }
        int i = 0;
        for (T c : collection) {
            visitor.visit(i++, c);
        }
    }

    private static<T> void foreach(Collection<T> collection, Filter<T> filter) {
        if (collection == null) {
            return;
        }
        for (T c : collection) {
            if (!filter.filter(c)) {
                return;
            }
        }
    }
}
